#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
"""
@File    :   Service.py
@Time    :   2022-10-23 23:00
@Author  :   坐公交也用券
@Version :   1.0
@Contact :   faith01238@hotmail.com
@Homepage : https://liumou.site
@Desc    :   服务配置管理 - 专注于服务配置文件的创建、更新、删除等管理
"""
import os
import re
import shutil
from typing import Optional, Dict, List

from . import Jurisdiction, NewCommand
from .logger import ColorLogger
from .OsInfo import OsInfo
from os import path


class ServiceConfig:
    def __init__(self, service, password, log=True):
        """
        服务配置管理
        :param service: 服务名称
        :param password: 密码
        :param log: 是否开启文本日志
        """
        # 参数校验
        if not service or not isinstance(service, str):
            raise ValueError("服务名称必须是非空字符串")
        if not password or not isinstance(password, str):
            raise ValueError("密码必须是非空字符串")

        self.log = log
        self._password = self._secure_password(password)  # 安全存储密码
        self.service = service

        # 初始化日志
        log_file = self._get_log_file_path()
        try:
            self.logger = ColorLogger(file=log_file, txt=log, class_name=self.__class__.__name__)
        except Exception as e:
            raise RuntimeError(f"日志初始化失败: {e}")

        # 初始化权限和命令模块
        try:
            self.ju = Jurisdiction(passwd=self._password, logs=log)
            self.cmd = NewCommand(password=self._password, logs=log)
        except Exception as e:
            self.logger.error(f"初始化权限或命令模块失败: {e}")
            raise

    def _secure_password(self, password):
        """
        对密码进行安全处理
        :param password: 明文密码
        :return: 安全存储的密码
        """
        return password[::-1]

    def _get_log_file_path(self):
        """
        获取日志文件路径
        :return: 日志文件路径
        """
        try:
            home_dir = OsInfo().home_dir
            if not home_dir:
                raise ValueError("无法获取用户主目录")
            return path.join(home_dir, 'ServiceConfig.log')
        except Exception as e:
            raise RuntimeError(f"日志文件路径生成失败: {e}")

    def create_service_file(self, config_content: str, service_name: Optional[str] = None, 
                          service_dir: str = "/etc/systemd/system") -> bool:
        """
        创建服务配置文件
        :param config_content: 服务配置内容
        :param service_name: 服务名称（可选，默认为实例服务名）
        :param service_dir: 服务文件目录，默认为 /etc/systemd/system
        :return: 创建是否成功
        """
        if service_name is None:
            service_name = self.service
        
        # 确保服务名称以 .service 结尾
        if not service_name.endswith('.service'):
            service_name += '.service'
        
        service_file_path = path.join(service_dir, service_name)
        
        try:
            # 检查目录是否存在，不存在则创建
            if not path.exists(service_dir):
                os.makedirs(service_dir, mode=0o755, exist_ok=True)
            
            # 写入服务配置文件
            with open(service_file_path, 'w', encoding='utf-8') as f:
                f.write(config_content)
            
            # 设置正确的文件权限
            os.chmod(service_file_path, 0o644)
            
            if self.log:
                self.logger.info(f"服务配置文件创建成功: {service_file_path}")
            
            return True
            
        except Exception as e:
            if self.log:
                self.logger.error(f"创建服务配置文件失败: {e}")
            return False

    def update_service_file(self, config_content: str, service_name: Optional[str] = None,
                          service_dir: str = "/etc/systemd/system") -> bool:
        """
        更新服务配置文件
        :param config_content: 新的服务配置内容
        :param service_name: 服务名称（可选，默认为实例服务名）
        :param service_dir: 服务文件目录，默认为 /etc/systemd/system
        :return: 更新是否成功
        """
        if service_name is None:
            service_name = self.service
        
        # 确保服务名称以 .service 结尾
        if not service_name.endswith('.service'):
            service_name += '.service'
        
        service_file_path = path.join(service_dir, service_name)
        
        try:
            # 检查文件是否存在
            if not path.exists(service_file_path):
                if self.log:
                    self.logger.warning(f"服务配置文件不存在: {service_file_path}")
                return False
            
            # 备份原文件
            backup_path = service_file_path + '.backup'
            shutil.copy2(service_file_path, backup_path)
            
            # 写入新的配置内容
            with open(service_file_path, 'w', encoding='utf-8') as f:
                f.write(config_content)
            
            if self.log:
                self.logger.info(f"服务配置文件更新成功: {service_file_path}")
            
            return True
            
        except Exception as e:
            if self.log:
                self.logger.error(f"更新服务配置文件失败: {e}")
            return False

    def delete_service_file(self, service_name: Optional[str] = None,
                          service_dir: str = "/etc/systemd/system") -> bool:
        """
        删除服务配置文件
        :param service_name: 服务名称（可选，默认为实例服务名）
        :param service_dir: 服务文件目录，默认为 /etc/systemd/system
        :return: 删除是否成功
        """
        if service_name is None:
            service_name = self.service
        
        # 确保服务名称以 .service 结尾
        if not service_name.endswith('.service'):
            service_name += '.service'
        
        service_file_path = path.join(service_dir, service_name)
        
        try:
            # 检查文件是否存在
            if not path.exists(service_file_path):
                if self.log:
                    self.logger.warning(f"服务配置文件不存在: {service_file_path}")
                return True  # 文件不存在，视为删除成功
            
            # 删除文件
            os.remove(service_file_path)
            
            if self.log:
                self.logger.info(f"服务配置文件删除成功: {service_file_path}")
            
            return True
            
        except Exception as e:
            if self.log:
                self.logger.error(f"删除服务配置文件失败: {e}")
            return False

    def get_service_config(self, service_name: Optional[str] = None,
                         service_dir: str = "/etc/systemd/system") -> Optional[str]:
        """
        获取服务配置文件内容
        :param service_name: 服务名称（可选，默认为实例服务名）
        :param service_dir: 服务文件目录，默认为 /etc/systemd/system
        :return: 配置文件内容，如果文件不存在则返回 None
        """
        if service_name is None:
            service_name = self.service
        
        # 确保服务名称以 .service 结尾
        if not service_name.endswith('.service'):
            service_name += '.service'
        
        service_file_path = path.join(service_dir, service_name)
        
        try:
            # 检查文件是否存在
            if not path.exists(service_file_path):
                if self.log:
                    self.logger.warning(f"服务配置文件不存在: {service_file_path}")
                return None
            
            # 读取文件内容
            with open(service_file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            if self.log:
                self.logger.info(f"成功读取服务配置文件: {service_file_path}")
            
            return content
            
        except Exception as e:
            if self.log:
                self.logger.error(f"读取服务配置文件失败: {e}")
            return None

    def validate_service_config(self, config_content: str) -> Dict[str, bool]:
        """
        验证服务配置文件的语法
        :param config_content: 服务配置内容
        :return: 验证结果字典
        """
        validation_result = {
            'has_unit_section': False,
            'has_service_section': False,
            'has_exec_start': False,
            'valid_structure': False
        }
        
        try:
            lines = config_content.strip().split('\n')
            current_section = None
            
            for line in lines:
                line = line.strip()
                if not line or line.startswith('#'):
                    continue
                
                # 检查节头
                if line.startswith('[') and line.endswith(']'):
                    current_section = line[1:-1].strip().lower()
                    if current_section == 'unit':
                        validation_result['has_unit_section'] = True
                    elif current_section == 'service':
                        validation_result['has_service_section'] = True
                
                # 在 Service 节中检查 ExecStart
                elif current_section == 'service' and line.lower().startswith('execstart'):
                    validation_result['has_exec_start'] = True
            
            # 验证基本结构
            validation_result['valid_structure'] = (
                validation_result['has_unit_section'] and 
                validation_result['has_service_section'] and 
                validation_result['has_exec_start']
            )
            
            if self.log:
                if validation_result['valid_structure']:
                    self.logger.info("服务配置文件语法验证通过")
                else:
                    self.logger.warning("服务配置文件语法验证未通过")
            
            return validation_result
            
        except Exception as e:
            if self.log:
                self.logger.error(f"服务配置文件语法验证失败: {e}")
            return validation_result

    def create_service_from_template(self, template_path: str, variables: Dict[str, str],
                                   service_name: Optional[str] = None,
                                   service_dir: str = "/etc/systemd/system") -> bool:
        """
        从模板创建服务配置文件
        :param template_path: 模板文件路径
        :param variables: 模板变量字典
        :param service_name: 服务名称（可选，默认为实例服务名）
        :param service_dir: 服务文件目录，默认为 /etc/systemd/system
        :return: 创建是否成功
        """
        if service_name is None:
            service_name = self.service
        
        try:
            # 读取模板文件
            with open(template_path, 'r', encoding='utf-8') as f:
                template_content = f.read()
            
            # 替换模板变量
            for key, value in variables.items():
                template_content = template_content.replace(f'{{{{{key}}}}}', value)
            
            # 创建服务配置文件
            return self.create_service_file(template_content, service_name, service_dir)
            
        except Exception as e:
            if self.log:
                self.logger.error(f"从模板创建服务配置文件失败: {e}")
            return False

    def list_service_files(self, service_dir: str = "/etc/systemd/system") -> List[str]:
        """
        列出指定目录中的所有服务配置文件
        :param service_dir: 服务文件目录，默认为 /etc/systemd/system
        :return: 服务文件列表
        """
        try:
            if not path.exists(service_dir):
                if self.log:
                    self.logger.warning(f"服务目录不存在: {service_dir}")
                return []
            
            service_files = []
            for filename in os.listdir(service_dir):
                if filename.endswith('.service'):
                    service_files.append(filename)
            
            if self.log:
                self.logger.info(f"找到 {len(service_files)} 个服务配置文件")
            
            return service_files
            
        except Exception as e:
            if self.log:
                self.logger.error(f"列出服务配置文件失败: {e}")
            return []

    def reload_systemd(self) -> bool:
        """
        重载 systemd 配置
        :return: 重载是否成功
        """
        try:
            result = self.cmd.sudo(cmd="systemctl daemon-reload", name="重载 systemd 配置")
            
            if result and self.log:
                self.logger.info("systemd 配置重载成功")
            elif not result and self.log:
                self.logger.error("systemd 配置重载失败")
            
            return result
            
        except Exception as e:
            if self.log:
                self.logger.error(f"重载 systemd 配置失败: {e}")
            return False

